﻿// ## 2023/10/27 # 铃 #完全汉化,简化代码,增加注释,优化函数处理 ##
// ## 2022/02/14 # 江东新风 # 部分常量中文化 ##
// ## 2021/01/23 # 江东新风 # 加入开启造币谷仓无需相邻时将不摆放位置 ##
// ## 2020/12/16 # messi # 优化语句 ##
// ## 2020/10/30 # 江东新风 # 同步马术书大神的更新 ##
// ## 2020/09/23 # 氕氘氚 # 修复交換内政设施失敗的問題 ##
// ## 2020/07/26 ##
/*
// 만든이: 기마책사
// Update: '18.12.7    / 최초적용: 收入设施_优化建设(조폐 주변 농장을 시장으로, 곡창 주변 시장을 농장으로 변경)
// Update: '19.1.5     / 변경내용: 收入设施_位置变更(멀리 떨어진 시장/농장을 조폐/곡창 주변의 보조시설과 위치 변경), 收入设施_重建(조폐/곡창 위치에 잘못 지어진 시설 재건축)
// Update: '19.1.9     / 변경내용: 收入设施_位置变更 조건 수정 (군둔농, 대도시 등 추가)
// Update: '19.1.30    / 변경내용: 실행무장 이름 추출 오류 수정
// Update: '19.2.25    / 변경내용: 重建_势力设置옵션 설명/스크립트 불일치 수정, 최적건설 및 위치이동 알고리즘에 세력설정 옵션 추가
// Update: '19.11.25   / 변경내용: 재건축 실행무장 선택 알고리즘 개선
// Update: '20.8.24    / 변경내용: core2.dll 신버젼 적용 시 收入设施_位置变更 기능 오류 수정
// Update: '20.9.20    / 변경내용: 收入设施_位置变更 조건 수정 (동작대, 공방, 조선, 생산시설3级 추가), 조폐/곡창 재건축 조건 수정
*/

namespace AI优化_内政设施
{
    //---------------------------------------------------------------------------------------
    // 用户设置（true=on，false=off）
    const bool 收入设施_优化建设 = true; // 市场/农场/造币/粮仓建设
    const int 最佳建设_势力设置 = 3;     // 0：全部适用，1：仅适用AI势力，2：完全适用Player势力，3：仅适用Player

    const bool 收入设施_位置变更 = true; // 将远离的市场/农场与造币/粮仓周边的辅助设施进行位置变更
    const int 变更位置_势力设置 = 3;     // 0：全部适用，1：仅适用AI势力，2：完全适用Player势力，3：仅适用Player

    //---------------------------------------------------------------------------------------
    const bool 收入设施_重建 = true; // 在建造错误的位置重建造币/粮仓
    const bool 重建_玩家确认 = true;
    const int 重建_城市标准金 = 500;
    const int 重建_势力设置 = 3; // 0：全部适用，1：仅适用AI势力，2：完全适用Player势力，3：仅适用Player

    //---------------------------------------------------------------------------------------

    class Main
    {

        Main()
        {
            pk::bind(111, pk::trigger111_t(onTurnStart));
            pk::bind(112, pk::trigger112_t(onTurnEnd));
        }

        void onTurnStart(pk::force @force)
        {
            if (pk::is_campaign())
                return;

            if (收入设施_优化建设)
                optimize_force_city_facility(force); // 优化收入相关内政设施建设
        }

        void onTurnEnd(pk::force @force)
        {
            if (pk::is_campaign())
                return;

            if (收入设施_位置变更 or 收入设施_重建)
                rebuild_force_city_facility(force); // 执行设施位置变更或重建
        }

        //---------------------------------------------------------------------------------------

        // 势力设置选项
        bool check_force_option(pk::force @force, bool enable, int option)
        {
            if (!enable)
                return false;
            // 当造币谷仓无需相邻时就不摆了
            if (造币谷仓无需相邻)
                return false;
            // 势力设置=0：全部适用，1:AI势力适用，2:Player势力全部适用，3:Player适用
            if (option == 0)
                return true;
            if (option == 1 and !force.is_player())
                return true;
            if (option == 2 and force.is_player())
                return true;
            if (option == 3 and pk::is_player_controlled(force))
                return true;

            return false;
        }

        //---------------------------------------------------------------------------------------
        // 优化收入设施
        //---------------------------------------------------------------------------------------

        void optimize_force_city_facility(pk::force @force)
        {
            pk::array<pk::city @> arr_city_list = pk::list_to_array(pk::get_city_list(force));
            for (int i = 0; i < int(arr_city_list.length); i++)
            {
                if (check_force_option(force, 收入设施_优化建设, 最佳建设_势力设置))
                    optimize_city_facility(arr_city_list[i]);
            }
        }

        // 按城市搜索和优化内政设施
        void optimize_city_facility(pk::city @city)
        {
            int force_id = city.get_force_id();
            if (city is null or !pk::is_valid_force_id(force_id))
                return;

            int sum_facility_hp = 0;
            for (int i = 0; i < int(city.max_devs); i++)
            {
                pk::building @building = city.dev[i].building;
                if (pk::is_alive(building))
                {
                    int facility_id = building.facility;

                    // 未完成造币/谷仓(优化收入设施)
                    if (!building.completed and (facility_id == 设施_谷仓 or facility_id == 设施_造币))
                    {
                        change_center_facility(building);
                    }

                    if (building.completed and (facility_id == 设施_谷仓 or facility_id == 设施_造币))
                    {
                        change_yield_facility(building);  // 未完成的周边农场/市场种类优化
                        change_assist_facility(building); // 将未完成的周边辅助设施改为市场/农场
                    }
                }
            }
        }

        //---------------------------------------------------------------------------------------

        // 未完成的周边生产设施变更
        void change_yield_facility(pk::building @building)
        {
            if (!pk::is_alive(building))
                return;
            if (!building.completed)
                return;

            int facility_id = building.facility;

            // 搜索完成的粮仓周边设施
            if (facility_id == 设施_谷仓)
            {
                for (int i = 0; i < 方向_末; i++)
                {
                    pk::point neighbor_pos = pk::get_neighbor_pos(building.pos, i);
                    if (pk::is_valid_pos(neighbor_pos))
                    {
                        pk::building @target_building = pk::get_building(neighbor_pos);
                        // 将未完成的周边市场改为农场
                        if (pk::is_alive(target_building) and !target_building.completed and target_building.facility == 设施_市场)
                        {
                            int count_neighbor = count_neighbor_facility(target_building, 设施_市场) + count_neighbor_facility(target_building, 设施_市场2级) + count_neighbor_facility(target_building, 设施_市场3级);

                            if (count_neighbor <= 3)
                            {
                                target_building.facility = 设施_农场;
                                target_building.update();
                            }
                        }
                    }
                }
            }

            // 搜索完成的造币周边设施
            if (facility_id == 设施_造币)
            {
                for (int i = 0; i < 方向_末; i++)
                {
                    pk::point neighbor_pos = pk::get_neighbor_pos(building.pos, i);
                    if (pk::is_valid_pos(neighbor_pos))
                    {
                        pk::building @target_building = pk::get_building(neighbor_pos);

                        // 将未完成的周边农场改为市场
                        if (pk::is_alive(target_building) and !target_building.completed and target_building.facility == 设施_农场)
                        {
                            int count_neighbor = count_neighbor_facility(target_building, 设施_农场) + count_neighbor_facility(target_building, 设施_农场2级) + count_neighbor_facility(target_building, 设施_农场3级);

                            if (count_neighbor <= 3)
                            {
                                target_building.facility = 设施_市场;
                                target_building.update();
                            }
                        }
                    }
                }
            }
        }

        //---------------------------------------------------------------------------------------

        // 要在该建筑物周围确认的设施数量计数
        int count_neighbor_facility(pk::building @building, int facility_id)
        {
            int count_facility = 0;

            for (int j = 0; j < 方向_末; j++)
            {
                pk::point neighbor_pos = pk::get_neighbor_pos(building.pos, j);
                if (pk::is_valid_pos(neighbor_pos))
                {
                    pk::building @neighbor_building = pk::get_building(neighbor_pos);
                    if (pk::is_alive(neighbor_building) and neighbor_building.facility == facility_id)
                        count_facility += 1;
                }
            }

            return count_facility;
        }

        //---------------------------------------------------------------------------------------

        // 未完成的周围支援设施更改
        void change_assist_facility(pk::building @building)
        {
            if (!pk::is_alive(building))
                return;
            if (!building.completed)
                return;

            int facility_id = building.facility;

            // 寻找完工的铸币/谷仓周围的市场
            if (facility_id == 设施_造币 or facility_id == 设施_谷仓)
            {
                int count_valid_pos = 0;
                int count_completed = 0;
                int count_uncompleted = 0;
                for (int i = 0; i < 方向_末; i++)
                {
                    pk::point neighbor_pos = pk::get_neighbor_pos(building.pos, i);
                    if (pk::is_valid_pos(neighbor_pos))
                    {
                        count_valid_pos += 1;

                        pk::building @target_building = pk::get_building(neighbor_pos);
                        if (pk::is_alive(target_building) and 设施_符节台 <= target_building.facility and target_building.facility <= 设施_练兵所)
                        {
                            // 周围辅助设施数量（完工、未完成）
                            if (target_building.completed)
                                count_completed += 1;
                            else
                                count_uncompleted += 1;
                        }
                    }
                }

                // 如果铸币/谷仓周围辅助设施过多，则将未完成的辅助设施改为市场/农场
                if ((count_completed + count_uncompleted) >= int((count_valid_pos + 1) / 3))
                {
                    for (int i = 0; i < 方向_末; i++)
                    {
                        pk::point neighbor_pos = pk::get_neighbor_pos(building.pos, i);
                        if (pk::is_valid_pos(neighbor_pos))
                        {
                            pk::building @target_building = pk::get_building(neighbor_pos);
                            if (pk::is_alive(target_building) and !target_building.completed and 设施_符节台 <= target_building.facility and target_building.facility <= 设施_练兵所)
                            {
                                if (facility_id == 设施_造币)
                                    target_building.facility = 设施_市场;
                                if (facility_id == 设施_谷仓)
                                    target_building.facility = 设施_农场;
                            }
                        }
                    }
                }
            }
        }
        //---------------------------------------------------------------------------------------

        // 未完成的中央设施更改
        void change_center_facility(pk::building @building)
        {
            if (!pk::is_alive(building))
                return;
            if (building.completed)
                return;

            int facility_id = building.facility;

            float count_ref = 3.0f;

            // 搜索未完成的造币厂或谷仓周围的农场
            if (facility_id == 设施_造币 or facility_id == 设施_谷仓)
            {
                float count_farm = 0.f;
                float count_market = 0.f;
                for (int i = 0; i < 方向_末; i++)
                {
                    pk::point neighbor_pos = pk::get_neighbor_pos(building.pos, i);
                    if (pk::is_valid_pos(neighbor_pos))
                    {
                        pk::building @target_building = pk::get_building(neighbor_pos);
                        if (pk::is_alive(target_building))
                        {
                            // 搜索周围的农场、2级农场和3级农场
                            if (target_building.facility == 设施_农场 and target_building.completed)
                                count_farm += 1.0f;
                            if (target_building.facility == 设施_农场2级)
                                count_farm += 1.25f;
                            if (target_building.facility == 设施_农场3级)
                                count_farm += 1.5f;

                            // 搜索周围的市场、2级市场和3级市场
                            if (target_building.facility == 设施_市场 and target_building.completed)
                                count_market += 1.0f;
                            if (target_building.facility == 设施_市场2级)
                                count_market += 1.25f;
                            if (target_building.facility == 设施_市场3级)
                                count_market += 1.5f;
                        }
                    }
                }
                // 如果农场数量满足条件，则将造币厂更改为谷仓设施
                if (facility_id == 设施_造币 and count_farm >= count_ref and count_farm > count_market)
                {
                    building.facility = 设施_谷仓;
                    building.update();
                }

                // 如果市场数量满足条件，则将谷仓更改为造币厂设施
                if (facility_id == 设施_谷仓 and count_market >= count_ref and count_market > count_farm)
                {
                    building.facility = 设施_造币;
                    building.update();
                }
            }
        }

        //---------------------------------------------------------------------------------------
        // 收入设施_位置变更 / 收入设施_重建
        //---------------------------------------------------------------------------------------

        // 势力城市
        void rebuild_force_city_facility(pk::force @force)
        {
            // 势力城市列表
            pk::array<pk::city @> arr_city_list = pk::list_to_array(pk::get_city_list(force));
            for (int i = 0; i < int(arr_city_list.length); i++)
            {
                if (pk::is_player_controlled(arr_city_list[i]))
                    continue;
                if (check_force_option(force, 收入设施_位置变更, 变更位置_势力设置))
                    swap_city_facility(arr_city_list[i]);

                if (check_force_option(force, 收入设施_重建, 重建_势力设置))
                    rebuild_city_facility(arr_city_list[i]);
            }
        }

        // 城市内已完成的生产设施/辅助设施位置变更
        void swap_city_facility(pk::city @city)
        {
            int force_id = city.get_force_id();
            if (city is null or !pk::is_valid_force_id(force_id))
                return;

            if (!check_city_dev_complete(city))
                return; // 建筑率确认

            // 已完成的生产设施/辅助设施位置互换
            swap_yield_facility(city);
        }

        // 城市的重建确认和执行
        void rebuild_city_facility(pk::city @city)
        {
            int force_id = city.get_force_id();
            if (city is null or !pk::is_valid_force_id(force_id))
                return;

            if (!check_city_dev_complete(city))
                return; // 建筑率确认
            if (city.max_devs <= 10)
                return; // 除了开发地数量极少的城市

            // 动作力和城市金钱条件确认
            if (int(pk::get_district(city.get_district_id()).ap) > 重建_标准行动力 and int(city.gold) > 重建_城市标准金)
            {
                for (int i = 0; i < int(city.max_devs); i++)
                {
                    pk::building @building = city.dev[i].building;
                    if (pk::is_alive(building))
                    {
                        rebuild_center_facility(city, building);
                    }
                }
            }
        }

        //---------------------------------------------------------------------------------------
        // 收入设施位置变更（将远离市场/农场的设施与造币厂/谷仓附近的辅助设施位置互换）

        // 城市设施互换
        void swap_yield_facility(pk::city @city)
        {
            if (!pk::is_alive(city))
                return;

            pk::building @src_building;
            pk::building @dst_building;
            int force_id = city.get_force_id();

            if (pk::has_facility(city, 设施_造币) and get_facility_count(city, 设施_市场3级) >= 2)
            {
                get_neighbor_assist_facility(city, 设施_造币, dst_building);
                if (pk::is_alive(dst_building))
                {
                    get_isolated_yield_facility(city, 设施_市场3级, 设施_造币, src_building);
                    get_neighbor_assist_facility(city, 设施_造币, dst_building);
                    swap_facility(src_building, dst_building, force_id); // 建筑更改

                    get_isolated_yield_facility(city, 设施_市场2级, 设施_造币, src_building);
                    get_neighbor_assist_facility(city, 设施_造币, dst_building);
                    swap_facility(src_building, dst_building, force_id); // 建筑更改

                    get_isolated_yield_facility(city, 设施_市场, 设施_造币, src_building);
                    get_neighbor_assist_facility(city, 设施_造币, dst_building);
                    swap_facility(src_building, dst_building, force_id); // 建筑更改
                }
            }

            if (pk::has_facility(city, 设施_谷仓) and get_facility_count(city, 设施_农场3级) >= 2)
            {
                get_neighbor_assist_facility(city, 设施_谷仓, dst_building);
                if (pk::is_alive(dst_building))
                {
                    get_isolated_yield_facility(city, 设施_农场3级, 设施_谷仓, src_building);
                    get_neighbor_assist_facility(city, 设施_谷仓, dst_building);
                    swap_facility(src_building, dst_building, force_id); // 建筑更改

                    get_isolated_yield_facility(city, 设施_农场2级, 设施_谷仓, src_building);
                    get_neighbor_assist_facility(city, 设施_谷仓, dst_building);
                    swap_facility(src_building, dst_building, force_id); // 建筑更改

                    get_isolated_yield_facility(city, 设施_农场, 设施_谷仓, src_building);
                    get_neighbor_assist_facility(city, 设施_谷仓, dst_building);
                    swap_facility(src_building, dst_building, force_id); // 建筑更改
                }
            }
        }
        // 搜索独立收入设施
        void get_isolated_yield_facility(pk::city @city, int facility_id, int neighbor_id, pk::building @ &out src_building)
        {
            if (!pk::is_alive(city))
                return;

            @src_building = null;
            for (int i = 0; i < int(city.max_devs); i++)
            {
                pk::building @building = city.dev[i].building;
                if (pk::is_alive(building))
                {
                    if (building.facility == facility_id and building.completed and count_neighbor_facility(building, neighbor_id) == 0)
                    {
                        @src_building = @building;
                        return;
                    }
                }
            }
        }

        // 搜索相邻的辅助设施
        void get_neighbor_assist_facility(pk::city @city, int facility_id, pk::building @ &out dst_building)
        {
            if (!pk::is_alive(city))
                return;

            @dst_building = null;
            for (int i = 0; i < int(city.max_devs); i++)
            {
                pk::building @building = city.dev[i].building;
                if (pk::is_alive(building) and building.facility == facility_id)
                {
                    // 搜索周围的辅助设施
                    for (int j = 0; j < 方向_末; j++)
                    {
                        pk::point neighbor_pos = pk::get_neighbor_pos(building.pos, j);
                        if (pk::is_valid_pos(neighbor_pos))
                        {
                            pk::building @building_t = pk::get_building(neighbor_pos);
                            if (pk::is_alive(building_t) and building_t.completed and ((设施_符节台 <= building_t.facility and building_t.facility <= 设施_军粮仓) or building_t.facility == 设施_铜雀台 or building_t.facility == 设施_工房 or building_t.facility <= 设施_造船 or building_t.facility == 设施_兵营3级 or building_t.facility == 设施_锻冶3级 or building_t.facility == 设施_厩舍3级))
                            {

                                for (int k = 0; k < int(city.max_devs); k++)
                                {
                                    pk::building @building_k = city.dev[k].building;
                                    if (pk::is_alive(building_k))
                                    {
                                        if (building_t.get_id() == building_k.get_id())
                                        {
                                            @dst_building = @building_t;
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // 设施互换函数
        void swap_facility(pk::building @src_building, pk::building @dst_building, int force_id)
        {
            if (!pk::is_valid_force_id(force_id))
                return;
            if (!pk::is_alive(src_building))
                return;
            if (!pk::is_alive(dst_building))
                return;

            int src_id = src_building.facility;
            if (src_id < 30 or src_id > 60)
                return;
            int dst_id = dst_building.facility;
            if (dst_id < 30 or dst_id > 60)
                return;
            pk::point src_pos = src_building.pos;
            pk::point dst_pos = dst_building.pos;
            int src_hp = src_building.hp;
            int dst_hp = dst_building.hp;

            // 在新版本 core2.dll 中出现错误，因此删除旧设施（'20.8.24）
            pk::kill(src_building, false);
            pk::kill(dst_building, false);

            pk::create_building(pk::get_facility(src_id), dst_pos, force_id);
            pk::building @new_src = pk::get_building(dst_pos);
            pk::complete(new_src);
            new_src.hp = src_hp; // 重设建筑耐久度（'20.9.20）
            new_src.update();

            pk::create_building(pk::get_facility(dst_id), src_pos, force_id);
            pk::building @new_dst = pk::get_building(src_pos);
            pk::complete(new_dst);
            new_dst.hp = dst_hp; // 重设建筑耐久度（'20.9.20）
            new_dst.update();
        }

        //---------------------------------------------------------------------------------------
        // 如果造币厂/谷仓位置错误重新建设

        int 重建_标准行动力 = 30; // 禁止修改！！
        int answer = 0;           // 0:是, 1:否, 2:是（继续）, 3:否（继续）

        // 重新建设中央设施位置
        void rebuild_center_facility(pk::city @city, pk::building @building)
        {
            if (!pk::is_alive(building))
                return;

            int count_neighbor = 0;
            int facility_id = building.facility;

            // 如果市场内不是市场/造币厂，则重新建设
            if (!pk::has_facility(city, 设施_造币))
            {
                count_neighbor = count_neighbor_facility(building, 设施_市场) + count_neighbor_facility(building, 设施_市场2级) + count_neighbor_facility(building, 设施_市场3级);
                if (count_neighbor >= 3 and facility_id != 设施_市场 and facility_id != 设施_市场2级 and facility_id != 设施_市场3级 and facility_id != 设施_造币)
                {
                    rebuild_facility(city, building, 设施_造币); // 重新建设造币厂
                }
            }

            // 如果农场内不是农场/谷仓，则重新建设
            if (!pk::has_facility(city, 设施_谷仓))
            {
                count_neighbor = count_neighbor_facility(building, 设施_农场1级) + count_neighbor_facility(building, 设施_农场2级) + count_neighbor_facility(building, 设施_农场3级);
                if (count_neighbor >= 3 and facility_id != 设施_农场1级 and facility_id != 设施_农场2级 and facility_id != 设施_农场3级 and facility_id != 设施_谷仓)
                {
                    rebuild_facility(city, building, 设施_谷仓); // 重新建设谷仓
                }
            }
        }

        //---------------------------------------------------------------------------------------

        // 根据重新建设条件进行重新建设
        void rebuild_facility(pk::city @city, pk::building @building, int rebuild_id)
        {
            // 获取行动力信息
            pk::district @district = pk::get_district(city.get_district_id());

            // 检查是否有可用的闲置武将
            pk::list<pk::person @> list_idle_person = pk::get_idle_person_list(pk::city_to_building(city));
            if (list_idle_person.count == 0)
                return;

            // 按照政治能力从高到低排序
            list_idle_person.sort(function(a, b) {
                return a.stat[武将能力_政治] > b.stat[武将能力_政治];
            });

            // 设施耐久度变化
            float hp_delta = float(int(pk::get_facility(rebuild_id).hp));

            // 计算参考工作天数和最小能力值
            pk::array<pk::person @> arr_idle_person = pk::list_to_array(list_idle_person);
            int min_actors = pk::min(3, pk::max(1, int(arr_idle_person.length) / 2)); // 自动选择适当人数
            float max_stat = 0.0f;
            for (int i = 0; i < min_actors; i++) // 最大可行能力值求和
            {
                float stat_weight;
                if (i == 0)
                    stat_weight = 1.5f;
                else
                    stat_weight = 0.5f;
                max_stat += float(arr_idle_person[i].stat[武将能力_政治]) * stat_weight;
            }
            int ref_per = int(hp_delta / max_stat) + (((hp_delta % max_stat) > 0) ? 1 : 0); // 建设期限计算（向上取整）
            float ref_stat = hp_delta / float(ref_per);                                     // 参考能力值

            // 自动选择适当人员
            pk::list<pk::person @> person_sel;
            float sum_stat = 0.0f;
            for (int i = 0; i < min_actors; i++)
            {
                float stat_weight;
                if (i == 0)
                    stat_weight = 1.5f;
                else
                    stat_weight = 0.5f;

                pk::person @actor_t;
                for (int j = (int(arr_idle_person.length) - 1); j >= 0; j--)
                {
                    if (!person_sel.contains(arr_idle_person[j]))
                    {
                        @actor_t = arr_idle_person[j];
                        if ((float(actor_t.stat[武将能力_政治]) * stat_weight + sum_stat) > ref_stat)
                            break;
                    }
                }
                if (pk::is_alive(actor_t))
                {
                    person_sel.add(actor_t);
                    sum_stat += actor_t.stat[武将能力_政治] * stat_weight;
                }
                if (sum_stat > ref_stat)
                    break;
            }
            pk::array<pk::person @> actors = pk::list_to_array(person_sel);

            // 黄金消费值（拆除建筑费用返还和重建费用）
            int gold_cost = int(pk::get_facility(rebuild_id).gold_cost) - int(pk::get_facility(building.facility).gold_cost);

            // 检查条件后执行重建
            if (int(district.ap) >= 重建_标准行动力 and pk::is_alive(actors[0]) and int(sum_stat) >= 70 and int(city.gold) > pk::max(gold_cost, 重建_城市标准金))
            {
                if (pk::is_player_controlled(city) and 重建_玩家确认 and answer <= 1)
                {
                    @building_t = @building;
                    pk::scene(pk::scene_t(goto_facility));

                    pk::person @kunshu = pk::get_person(pk::get_kunshu_id(city));
                    string actor_name;
                    for (int i = 0; i < int(actors.length); i++)
                    {
                        pk::person @actor_t = actors[i];
                        if (i == 0)
                            actor_name = pk::decode(pk::get_name(actor_t));
                        else
                            actor_name = actor_name + "," + pk::decode(pk::get_name(actor_t));
                    }
                    string city_name = pk::decode(pk::get_name(city));
                    string facility_name1 = pk::decode(pk::get_facility(building.facility).name);
                    string facility_name2 = pk::decode(pk::get_facility(rebuild_id).name);

                    answer = pk::choose({pk::encode(" 是 "), pk::encode(" 否 "), pk::encode("是(继续)"), pk::encode("否(继续)")},
                                        pk::encode(pk::format("是否要派遣\x1b[1x{}\x1b[0x在\x1b[1x{}\x1b[0x重建\x1b[1x{}\x1b[0x和\x1b[1x{}\x1b[0x?\n (花费 {} 资金)", actor_name, city_name, facility_name1, facility_name2, gold_cost)),
                                        kunshu);

                    pk::scene(pk::scene_t(remove_highlights));
                }

                // 执行重建
                if ((pk::is_player_controlled(city) and (answer == 0 or answer == 2)) or !pk::is_player_controlled(city))
                {
                    // 如果要重建的建筑物是必要设施，则确保追加建设用地
                    if (check_essential_facility(building.facility))
                        remove_assist_facility(city, building);
                    // 重建执行函数
                    rebuild_command(city, building, actors, rebuild_id);
                    // 返还被拆除建筑的费用并减少重建费用
                    pk::add_gold(city, -gold_cost, true);
                }
            }
        }

        //---------------------------------------------------------------------------------------

        // 重建执行函数
        void rebuild_command(pk::city @city, pk::building @building, pk::array<pk::person @> actors, int rebuild_id)
        {
            // 建筑信息
            pk::develop_cmd_info cmd_develop;
            @cmd_develop.base = pk::city_to_building(city);
            for (int i = 0; i < int(actors.length); i++)
            {
                @cmd_develop.actors[i] = actors[i];
            }
            cmd_develop.facility = rebuild_id;
            cmd_develop.pos = building.pos;

            // 删除现有建筑物（无动画效果）
            pk::kill(building, false);
            pk::district @district = pk::get_district(city.get_district_id());
            pk::add_ap(district, -10);

            // 建筑运行
            pk::command(cmd_develop);
        }

        //---------------------------------------------------------------------------------------

        void goto_facility()
        {
            pk::point pos = building_t.pos;
            for (int i = 0; i < 4; i++)
            {
                pk::point pos_t;
                pos_t.x = pos.x + 1;
                pos_t.y = pos.y;
                if (pk::is_valid_pos(pos_t))
                    pos.x = pos.x + 1;
            }

            if (!pk::is_in_screen(pos))
                pk::move_screen(pos, 1);

            pk::highlight(building_t.pos, true);
        }
        void remove_highlights()
        {
            pk::remove_all_highlights();
        }

        pk::building @building_t;

        //---------------------------------------------------------------------------------------

        // 确认内定设施建设率是否100%
        bool check_city_dev_complete(pk::city @city)
        {
            if (city.num_devs < city.max_devs)
                return false;

            return true;
        }

        //---------------------------------------------------------------------------------------

        // 确认是否为必要设施
        bool check_essential_facility(int facility_id)
        {
            if (facility_id <= 设施_谷仓 or facility_id >= 设施_市场2级)
                return true;
            if (facility_id == 设施_大市场 or facility_id == 设施_渔市)
                return true;

            return false;
        }

        // 为确保建设用地强制拆除1个辅助设施
        void remove_assist_facility(pk::city @city, pk::building @building_self)
        {
            bool removed = false;
            int count_facility = 0;

            if (pk::has_facility(city, 设施_军粮仓))
            {
                removed = remove_facility(city, building_self, 设施_军粮仓);
                if (removed)
                    return;
            }
            for (int remove_id = 设施_符节台; remove_id <= 设施_练兵所; remove_id++)
            {
                if (pk::has_facility(city, remove_id))
                {
                    removed = remove_facility(city, building_self, remove_id);
                    if (removed)
                        return;
                }
            }
            if (pk::has_facility(city, 设施_军粮仓))
            {
                removed = remove_facility(city, building_self, 设施_军粮仓);
                if (removed)
                    return;
            }

            count_facility = get_facility_count(city, 设施_谷仓);
            if (count_facility > 1) // 如果建了多个谷仓，完成的建筑物将被拆除
            {
                for (int i = 0; i < count_facility; i++)
                {
                    removed = remove_facility(city, building_self, 设施_谷仓);
                    if (removed)
                        return;
                }
            }
            count_facility = get_facility_count(city, 设施_造币);
            if (count_facility > 1) // 如果建造了多个造币，完成的建筑物将被拆除
            {
                for (int i = 0; i < count_facility; i++)
                {
                    removed = remove_facility(city, building_self, 设施_造币);
                    if (removed)
                        return;
                }
            }

            if (pk::has_facility(city, 设施_工房))
            {
                removed = remove_facility(city, building_self, 设施_工房);
                if (removed)
                    return;
            }
            if (pk::has_facility(city, 设施_造船))
            {
                removed = remove_facility(city, building_self, 设施_造船);
                if (removed)
                    return;
            }
        }

        // 强制拆除完成的设施
        bool remove_facility(pk::city @city, pk::building @building_self, int remove_id)
        {
            pk::district @district = pk::get_district(city.get_district_id());
            int gold_cost = int(pk::get_facility(remove_id).gold_cost);

            for (int i = 0; i < int(city.max_devs); i++)
            {
                pk::building @building = city.dev[i].building;
                if (pk::is_alive(building))
                {
                    if (building.facility == remove_id and building.completed and building.pos != building_self.pos)
                    {
                        // 保护强制拆除的行动力和拆除设施费用
                        pk::add_ap(district, 10); // district.ap += 10;
                        pk::add_gold(city, gold_cost, false);

                        // 强制拆除
                        pk::destroy_cmd_info cmd_destroy;
                        @cmd_destroy.building = building;
                        pk::command(cmd_destroy);

                        return true; // 强制拆除完毕
                    }
                }
            }
            return false; // 拆除失败
        }

        // 完成的设施数量计数函数
        int get_facility_count(pk::city @city, int count_id)
        {
            int count = 0;
            for (int i = 0; i < int(city.max_devs); i++)
            {
                pk::building @building = city.dev[i].building;
                if (pk::is_alive(building))
                {
                    if (building.facility == count_id)
                        count += 1;
                }
            }
            return count;
        }

        //---------------------------------------------------------------------------------------
    }

    Main main;
}
